A useful programming paradigm is often referred as “reactive programming” or “event-driven programming”. In this paradigm, an object registers event handlers (which are software routines) that are invoked in response to predetermined events. For example, a software module may wish to be notified of a change to the value of a particular variable. To do so, the software module can register a handler so that upon a change to the particular variable, the handler is informed about the change. Multiple event handlers can be registered by the software module (or by plural software modules) to monitor changes to the particular variable (or to monitor other events).
Generally, the reactive programming or event-driven programming paradigm works well for software modules that transition from one mode or state to another mode or state in response to external events or to changes made to atomic variables (such as numbers or Boolean values). However, conventional systems do not efficiently handle events that represent changes to a collection of items.
For example, in the JavaBeans model, a collection of items can be represented as a bound property of an object and associated with one or more listeners. When a change occurs to a bound property, registered listeners are notified by means of an event that identifies the object whose property changed, the name of the property that changed, and the old and new values of the property. There are several conventional approaches to providing event objects for changes in bound properties that represent collections. In a first conventional approach, when a collection is modified by adding or deleting values, both the new value and old value referenced by the event point to the same collection object. In this first approach, a listener has no way of knowing what change has just occurred in the collection.
In a second conventional approach, a collection is copied before the change occurs, and both the old value and new value are passed to a listener. However, in this second approach, unnecessary copying is performed, which is wasteful of processing and storage resources of a system. Also, if the old value referenced by the event is the identical object as the collection prior to the change, any prior references to the collection previously acquired by any software module will no longer refer to the current value.
With either the first or second approach, the decision to propagate an event is made outside the collection object itself, which may be difficult to handle because external code has to be written to make the decision for propagating an event representing a change to the collection. Also, conventionally, any modification to the collection would have to be made through the application programming interface (API) of a containing object of the collection, since any changes made directly to the collection will not be propagated.
Moreover, conventional event propagation mechanisms do not handle multiple changes to a collection efficiently. If there are multiple changes to a collection, each listener will be called multiple times. For example, if item A is added to a collection and item B is added to the collection, then a listener would be called twice for the two changes to the collection. Even worse, if item A is added to a collection, and item A is later removed from the collection, then a listener would also be called twice for the two change events, even though the two changes effectively cancel each other out such that the collection has not actually been changed.
Conventional event propagation mechanisms also do not handle nested changes to a collection very efficiently. For example, if a first change (such as the addition of item A) is made to a collection, a list of listeners is called to notify the listeners of the change. Typically, these listeners will be called sequentially. However, in some cases, one of the listeners may actually make a further change to the collection (e.g., addition of item B to the collection), which may then cause a second round of calls to the list of listeners interested in changes to the collection. In many common implementations the two (or more) events received by a listener in such situations may be received out of order (e.g., receiving notification of the addition of item B before receiving notification of the addition of item A) and/or may lead it to infer that the collection results in the same final state following each received event.